﻿// Log4NetCtrl
// Log4Net Appender / User control for Windows Forms
// Copyright (C) 2009 Ralph Greschner
// 
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
// 
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
// 
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
// Version history:
// ====================
//
// 04/10/2009: initial release
//   - still considered BETA
//


using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Collections.Generic;
using log4net;

namespace Log4NetCtrl
{
	/// <summary>
	/// Log4NetCtrl WinForms User Control class.
	/// This class provides a graphical
	/// display for appended log messages.
	/// </summary>
	public partial class Log4NetCtrl : UserControl
	{
		#region Constructors
		
		/// <summary>
		/// Default ctor.
		/// </summary>
		public Log4NetCtrl()
		{
			// set redirector instance
			redirector = new AppenderRedirector(this);
			
			this.InitializeComponent();
		}
		
		#endregion
		
		#region Class members
		
		/// <summary>
		/// Redirector for redirecting
		/// Appender events to this control.
		/// </summary>
		AppenderRedirector redirector;
		
		/// <summary>
		/// List for storage of LoggingEvents.
		/// </summary>
		List<log4net.Core.LoggingEvent> loggedEvents = new List<log4net.Core.LoggingEvent>();
		
		/// <summary>
		/// Buffer size, which determines maximum number of
		/// stored elements.
		/// </summary>
		int bufferSize = 0;
		
		#endregion
		
		#region Getters / Setters
		
		/// <summary>
		/// Redirector for inner Appender.
		/// Implements IAppender for use with
		/// log4net.
		/// </summary>
		public log4net.Appender.IAppender Appender {
			get {
				return (log4net.Appender.IAppender)redirector;
			}
		}
		/// <summary>
		/// The buffer size determines
		/// how many LoggedEvents are stored
		/// in the control.
		/// Size = 0: no limit.
		/// Size > 0: limited number of stored events.
		/// </summary>
		public int BufferSize {
			set {
				// buffer size has to be >= 0
				if (value >= 0){
					// only resize if value has changed
					if (value != bufferSize){
						bufferSize = value;
						ResizeBuffer();
					}
				}
			}
			get {
				return bufferSize;
			}
		}
		
		#endregion
		
		# region Private methods
		
		/// <summary>
		/// Resize the number
		/// of events cached.
		/// </summary>
		void ResizeBuffer(){
	
			// buffer size < 0 is impossible
			if(bufferSize < 0)
				bufferSize = 0;
			
			// buffer size of 0 means:
			// no size limit
			if(bufferSize == 0){
				return ;
			}
				
			// if buffer size > 0,
			// we may have to delete
			// older logged events
			if (bufferSize > 0){
				
				while ( listView1.Items.Count > bufferSize)
					listView1.Items.RemoveAt(0);
				
				while ( loggedEvents.Count > bufferSize)
					loggedEvents.RemoveAt(0);
				
			}
			
			// adjust number of listview items to
			// match buffer size
			while (listView1.Items.Count < bufferSize)
				listView1.Items.Add(" ");
			
			
		}
		
		
		
		
		/// <summary>
		/// Set text of listview items to LoggingEvent log message.
		/// </summary>
		void ModifyListView(){
			listView1.SuspendLayout();
			for(int i=0; i<loggedEvents.Count; ++i){
				if (bufferSize == 0 && listView1.Items.Count < loggedEvents.Count)
					listView1.Items.Add(" ");
			
				this.listView1.Items[i].Text = loggedEvents[i].MessageObject.ToString();
			}
			listView1.ResumeLayout();
			listView1.Invalidate();
		}
		
		/// <summary>
		/// Add loggingEvent to list.
		/// </summary>
		/// <param name="loggingEvent">Event to log.</param>
		void AppenderDoAppend(log4net.Core.LoggingEvent loggingEvent)
		{
			// remove first element until
			// enough space in list to
			// be < bufferSize
			if (bufferSize > 0){
				while(loggedEvents.Count+1 > bufferSize){
					loggedEvents.RemoveAt(0);
				}
			}
			
			// add event
			loggedEvents.Add(loggingEvent);
			
			// invalidate control's listview
			if (!this.InvokeRequired)
				ModifyListView();
			else
				this.Invoke(new MethodInvoker(this.ModifyListView));
			

		}
		
		#endregion
	}
}
